package com.jxs.android.weiget;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.jxs.android.cmcc.R;
import com.jxs.android.util.BitmapUtil;
import com.jxs.android.util.MathUtil;
import com.jxs.android.util.RoundUtil;

public class GesturePwdView extends View {
	private float width = 0;
	private float height = 0;

	//
	private boolean isCache = false;
	//
	private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

	//
	private GesturePwdPoint[][] mPoints = new GesturePwdPoint[3][3];
	// 圆的半径
	private float radius = 0;
	// 选中的点
	private List<GesturePwdPoint> sPoints = new ArrayList<GesturePwdPoint>();
	private boolean checking = false;
	private Bitmap gesture_pwd_round_original;
	private Bitmap gesture_pwd_round_click;
	private Bitmap gesture_pwd_round_click_error;
	private Bitmap gesture_pwd_line;
	private Bitmap gesture_pwd_line_semicircle;
	private Bitmap gesture_pwd_line_semicircle_error;
	private Bitmap gesture_pwd_arrow;
	private Bitmap gesture_pwd_line_error;
	private long CLEAR_TIME = 500;
	private boolean isTouch = true; // 是否可操作
	private Matrix mMatrix = new Matrix();
	private int lineAlpha = 100;
	private int minPwdLength = 0;

	public GesturePwdView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public GesturePwdView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public GesturePwdView(Context context) {
		super(context);
	}

	@Override
	public void onDraw(Canvas canvas) {
		if (!isCache) {
			initCache();
		}
		drawToCanvas(canvas);
	}

	private void drawToCanvas(Canvas canvas) {

		for (int i = 0; i < mPoints.length; i++) {// 画所有点
			for (int j = 0; j < mPoints[i].length; j++) {
				GesturePwdPoint p = mPoints[i][j];
				if (p.state == GesturePwdPoint.STATE_CHECK) {
					canvas.drawBitmap(gesture_pwd_round_click, p.x - radius, p.y - radius, mPaint);
				} else if (p.state == GesturePwdPoint.STATE_CHECK_ERROR) {
					canvas.drawBitmap(gesture_pwd_round_click_error, p.x - radius, p.y - radius, mPaint);
				} else {
					canvas.drawBitmap(gesture_pwd_round_original, p.x - radius, p.y - radius, mPaint);
				}
			}
		}

		if (sPoints.size() > 0) {// 画连线
			int tmpAlpha = mPaint.getAlpha();
			mPaint.setAlpha(lineAlpha);
			GesturePwdPoint tp = sPoints.get(0);
			for (int i = 1; i < sPoints.size(); i++) {
				GesturePwdPoint p = sPoints.get(i);
				drawLine(canvas, tp, p);
				tp = p;
			}
			if (this.movingNoPoint) {
				drawLine(canvas, tp, new GesturePwdPoint((int) moveingX, (int) moveingY));
			}
			mPaint.setAlpha(tmpAlpha);
			lineAlpha = mPaint.getAlpha();
		}

	}

	/**
	 * 初始化Cache信息
	 * 
	 * @param canvas
	 */
	private void initCache() {

		width = this.getWidth();
		height = this.getHeight();
		float x = 0;
		float y = 0;

		// 以最小的为准
		// 纵屏
		if (width > height) {
			x = (width - height) / 2;
			width = height;
		}
		// 横屏
		else {
			y = (height - width) / 2;
			height = width;
		}

		gesture_pwd_round_original = BitmapFactory.decodeResource(this.getResources(), R.drawable.gesture_pwd_round_original);
		gesture_pwd_round_click = BitmapFactory.decodeResource(this.getResources(), R.drawable.gesture_pwd_round_click);
		gesture_pwd_round_click_error = BitmapFactory.decodeResource(this.getResources(), R.drawable.gesture_pwd_round_click_error);

		gesture_pwd_line = BitmapFactory.decodeResource(this.getResources(), R.drawable.gesture_pwd_line);
		gesture_pwd_line_semicircle = BitmapFactory.decodeResource(this.getResources(), R.drawable.gesture_pwd_line_semicircle);

		gesture_pwd_line_error = BitmapFactory.decodeResource(this.getResources(), R.drawable.gesture_pwd_line_error);
		gesture_pwd_line_semicircle_error = BitmapFactory.decodeResource(this.getResources(), R.drawable.gesture_pwd_line_semicircle_error);

		gesture_pwd_arrow = BitmapFactory.decodeResource(this.getResources(), R.drawable.gesture_pwd_arrow);

		// 计算圆圈图片的大小
		float canvasMinW = width;
		if (width > height) {
			canvasMinW = height;
		}
		float roundMinW = canvasMinW / 8.0f * 2;
		float roundW = roundMinW / 2.f;
		//
		float deviation = canvasMinW % (8 * 2) / 2;
		x += deviation;
		x += deviation;

		if (gesture_pwd_round_original.getWidth() > roundMinW) {
			float sf = roundMinW * 1.0f / gesture_pwd_round_original.getWidth(); // 取得缩放比例，将所有的图片进行缩放
			gesture_pwd_round_original = BitmapUtil.zoom(gesture_pwd_round_original, sf);
			gesture_pwd_round_click = BitmapUtil.zoom(gesture_pwd_round_click, sf);
			gesture_pwd_round_click_error = BitmapUtil.zoom(gesture_pwd_round_click_error, sf);

			gesture_pwd_line = BitmapUtil.zoom(gesture_pwd_line, sf);
			gesture_pwd_line_semicircle = BitmapUtil.zoom(gesture_pwd_line_semicircle, sf);

			gesture_pwd_line_error = BitmapUtil.zoom(gesture_pwd_line_error, sf);
			gesture_pwd_line_semicircle_error = BitmapUtil.zoom(gesture_pwd_line_semicircle_error, sf);
			gesture_pwd_arrow = BitmapUtil.zoom(gesture_pwd_arrow, sf);
			roundW = gesture_pwd_round_original.getWidth() / 2;
		}

		mPoints[0][0] = new GesturePwdPoint(x + 0 + roundW, y + 0 + roundW);
		mPoints[0][1] = new GesturePwdPoint(x + width / 2, y + 0 + roundW);
		mPoints[0][2] = new GesturePwdPoint(x + width - roundW, y + 0 + roundW);
		mPoints[1][0] = new GesturePwdPoint(x + 0 + roundW, y + height / 2);
		mPoints[1][1] = new GesturePwdPoint(x + width / 2, y + height / 2);
		mPoints[1][2] = new GesturePwdPoint(x + width - roundW, y + height / 2);
		mPoints[2][0] = new GesturePwdPoint(x + 0 + roundW, y + height - roundW);
		mPoints[2][1] = new GesturePwdPoint(x + width / 2, y + height - roundW);
		mPoints[2][2] = new GesturePwdPoint(x + width - roundW, y + height - roundW);
		int k = 0;
		for (GesturePwdPoint[] ps : mPoints) {
			for (GesturePwdPoint p : ps) {
				p.index = k;
				k++;
			}
		}
		radius = gesture_pwd_round_original.getHeight() / 2;// roundW;
		isCache = true;
	}

	/**
	 * 画两点的连接
	 * 
	 * @param canvas
	 * @param a
	 * @param b
	 */
	private void drawLine(Canvas canvas, GesturePwdPoint a, GesturePwdPoint b) {
		float ah = (float) MathUtil.distance(a.x, a.y, b.x, b.y);
		float degrees = getDegrees(a, b);
		canvas.rotate(degrees, a.x, a.y);

		if (a.state == GesturePwdPoint.STATE_CHECK_ERROR) {
			mMatrix.setScale((ah - gesture_pwd_line_semicircle_error.getWidth()) / gesture_pwd_line_error.getWidth(), 1);
			mMatrix.postTranslate(a.x, a.y - gesture_pwd_line_error.getHeight() / 2.0f);
			canvas.drawBitmap(gesture_pwd_line_error, mMatrix, mPaint);
			canvas.drawBitmap(gesture_pwd_line_semicircle_error, a.x + gesture_pwd_line_error.getWidth(), a.y - gesture_pwd_line_error.getHeight() / 2.0f, mPaint);
		} else {
			mMatrix.setScale((ah - gesture_pwd_line_semicircle.getWidth()) / gesture_pwd_line.getWidth(), 1);
			mMatrix.postTranslate(a.x, a.y - gesture_pwd_line.getHeight() / 2.0f);
			canvas.drawBitmap(gesture_pwd_line, mMatrix, mPaint);
			canvas.drawBitmap(gesture_pwd_line_semicircle, a.x + ah - gesture_pwd_line_semicircle.getWidth(), a.y - gesture_pwd_line.getHeight() / 2.0f, mPaint);
		}

		canvas.drawBitmap(gesture_pwd_arrow, a.x, a.y - gesture_pwd_arrow.getHeight() / 2.0f, mPaint);

		canvas.rotate(-degrees, a.x, a.y);

	}

	public float getDegrees(GesturePwdPoint a, GesturePwdPoint b) {
		float ax = a.x;// a.index % 3;
		float ay = a.y;// a.index / 3;
		float bx = b.x;// b.index % 3;
		float by = b.y;// b.index / 3;
		float degrees = 0;
		if (bx == ax) {// y轴相等 90度或270
			if (by > ay) {// 在y轴的下边 90
				degrees = 90;
			} else if (by < ay) {// 在y轴的上边 270
				degrees = 270;
			}
		} else if (by == ay) {// y轴相等 0度或180
			if (bx > ax) {// 在y轴的下边 90
				degrees = 0;
			} else if (bx < ax) {// 在y轴的上边 270
				degrees = 180;
			}
		} else {
			if (bx > ax) { // 在y轴的右边 270~90
				if (by > ay) {// 在y轴的下边 0 - 90
					degrees = 0;
					degrees = degrees + switchDegrees(Math.abs(by - ay), Math.abs(bx - ax));
				} else if (by < ay) {// 在y轴的上边 270~0
					degrees = 360;
					degrees = degrees - switchDegrees(Math.abs(by - ay), Math.abs(bx - ax));
				}

			} else if (bx < ax) {// 在y轴的左边 90~270
				if (by > ay) {// 在y轴的下边 180 ~ 270
					degrees = 90;
					degrees = degrees + switchDegrees(Math.abs(bx - ax), Math.abs(by - ay));
				} else if (by < ay) {// 在y轴的上边 90 ~ 180
					degrees = 270;
					degrees = degrees - switchDegrees(Math.abs(bx - ax), Math.abs(by - ay));
				}

			}
		}
		return degrees;
	}

	/**
	 * 1=30度 2=45度 4=60度
	 * 
	 * @param tan
	 * @return
	 */
	private float switchDegrees(float x, float y) {
		return (float) MathUtil.pointTotoDegrees(x, y);
	}

	/**
	 * 取得数组下标
	 * 
	 * @param index
	 * @return
	 */
	public int[] getArrayIndex(int index) {
		int[] ai = new int[2];
		ai[0] = index / 3;
		ai[1] = index % 3;
		return ai;
	}

	/**
	 * 
	 * 检查
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	private GesturePwdPoint checkSelectPoint(float x, float y) {
		for (int i = 0; i < mPoints.length; i++) {
			for (int j = 0; j < mPoints[i].length; j++) {
				GesturePwdPoint p = mPoints[i][j];
				if (RoundUtil.checkInRound(p.x, p.y, radius, (int) x, (int) y)) {
					return p;
				}
			}
		}
		return null;
	}

	/**
	 * 重置
	 */
	private void reset() {
		for (GesturePwdPoint p : sPoints) {
			p.state = GesturePwdPoint.STATE_NORMAL;
		}
		sPoints.clear();
		this.enableTouch();
	}

	/**
	 * 判断点是否有交叉 返回 0,新点 ,1 与上一点重叠 2,与非最后一点重叠
	 * 
	 * @param p
	 * @return
	 */
	private int crossPoint(GesturePwdPoint p) {
		// 重叠的不最后一个则 reset
		if (sPoints.contains(p)) {
			if (sPoints.size() > 2) {
				// 与非最后一点重叠
				if (sPoints.get(sPoints.size() - 1).index != p.index) {
					return 2;
				}
			}
			return 1; // 与最后一点重叠
		} else {
			return 0; // 新点
		}
	}

	/**
	 * 添加一个点
	 * 
	 * @param point
	 */
	private void addPoint(GesturePwdPoint point) {
		this.sPoints.add(point);
	}

	/**
	 * 转换为String
	 * 
	 * @param points
	 * @return
	 */
	private String toPointString() {
		StringBuffer sf = new StringBuffer("");
		for (GesturePwdPoint p : sPoints) {
			sf.append(p.index);
		}
		return sf.toString();
	}

	boolean movingNoPoint = false;
	float moveingX, moveingY;

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// 不可操作
		if (!isTouch) {
			return false;
		}

		movingNoPoint = false;

		float ex = event.getX();
		float ey = event.getY();
		boolean isFinish = false;
		GesturePwdPoint p = null;
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN: // 点下
			// 如果正在清除密码,则取消
			if (task != null) {
				task.cancel();
				task = null;
				Log.d("task", "touch cancel()");
			}
			// 删除之前的点
			reset();
			p = checkSelectPoint(ex, ey);
			if (p != null) {
				checking = true;
			}
			break;
		case MotionEvent.ACTION_MOVE: // 移动
			if (checking) {
				p = checkSelectPoint(ex, ey);
				if (p == null) {
					movingNoPoint = true;
					moveingX = ex;
					moveingY = ey;
				}
			}
			break;
		case MotionEvent.ACTION_UP: // 提起
			p = checkSelectPoint(ex, ey);
			checking = false;
			isFinish = true;
			break;
		}
		if (!isFinish && checking && p != null) {

			int rk = crossPoint(p);
			if (rk == 2) {// 与非最后一重叠
				movingNoPoint = true;
				moveingX = ex;
				moveingY = ey;
			} else if (rk == 0) {// 一个新点
				p.state = GesturePwdPoint.STATE_CHECK;
				addPoint(p);
			}

		}

		if (isFinish) {
			if (this.sPoints.size() == 1) {
				this.reset();
			} else if (gesturePwdListener != null) {
				if (this.sPoints.size() < minPwdLength && this.sPoints.size() > 0) {
					error();
					clearPassword();
					gesturePwdListener.error();
				} else if (this.sPoints.size() >= minPwdLength) {
					this.disableTouch();
					gesturePwdListener.onComplete(toPointString());
				}
			}
		}
		this.postInvalidate();
		return true;
	}

	/**
	 * 设置已经选中的为错误
	 */
	private void error() {
		for (GesturePwdPoint p : sPoints) {
			p.state = GesturePwdPoint.STATE_CHECK_ERROR;
		}
	}

	/**
	 * 设置为输入错误
	 */
	public void markError() {
		markError(CLEAR_TIME);
	}

	/**
	 * 设置为输入错误
	 */
	public void markError(final long time) {
		for (GesturePwdPoint p : sPoints) {
			p.state = GesturePwdPoint.STATE_CHECK_ERROR;
		}
		this.clearPassword(time);
	}

	/**
	 * 设置为可操作
	 */
	public void enableTouch() {
		isTouch = true;
	}

	/**
	 * 设置为不可操作
	 */
	public void disableTouch() {
		isTouch = false;
	}

	private Timer timer = new Timer();
	private TimerTask task = null;

	/**
	 * 清除密码
	 */
	public void clearPassword() {
		clearPassword(CLEAR_TIME);
	}

	/**
	 * 清除密码
	 */
	private void clearPassword(final long time) {
		if (time > 1) {
			if (task != null) {
				task.cancel();
			}
			lineAlpha = 130;
			postInvalidate();
			task = new TimerTask() {
				public void run() {
					reset();
					postInvalidate();
				}
			};
			timer.schedule(task, time);
		} else {
			reset();
			postInvalidate();
		}

	}

	private GesturePwdListener gesturePwdListener;

	/**
	 * @param gesturePwdListener
	 */
	public void setGesturePwdListener(GesturePwdListener gesturePwdListener) {
		this.gesturePwdListener = gesturePwdListener;
		this.minPwdLength = this.gesturePwdListener.minPwdLength();
	}

	static public interface GesturePwdListener {
		public void onComplete(String password);

		public int minPwdLength();

		public void error();

	}
}
